# 2023-12-15稳定版，无合同采购功能
from DrissionPage import ChromiumPage  # 导入浏览器类
from DrissionPage._elements.chromium_element import ChromiumElement  # 导入element类型
import re, time, pysnooper
from DrissionPage.common import Actions
from DrissionPage.errors import ElementNotFoundError
from datetime import datetime

web: ChromiumPage = ChromiumPage()
ac = Actions(web)
# https://curlconverter.com/  curl转换工具
# web.get("https://www.simcompanies.com/zh/landscape/")
time.sleep(3)
# web.stop_loading()
print("请登录，进入游戏主界面")


def number_str_to_float(txt: str, roundUp: int = 1) -> float:
    """将价格str转换为float
    :txt: 要转换的字符串,
    :roundUp: 转换后要除以的值，通常为100，将价格4643变为46.43
    """
    match1: list[str] = re.findall(r"[-?0-9]+\.?", txt)
    c = ""
    match2: str = c.join(match1)
    nums: float = float(match2)
    nums = round(nums, 2)
    return nums / roundUp


class Wares:
    """仓库类"""

    def __init__(self) -> None:
        self.number_of_item_types: list[ItemType] = []

    def get_all_types(self):
        """仓库获取所有物品信息"""
        eles1: list[ChromiumElement] = web.eles(
            'x://b[text()="运输单位"]/../../../../../div'
        )
        """仓库eles的list"""
        for ele in eles1:
            i_list: list[ChromiumElement | str] = ele.eles("x://img/..")
            for a in i_list:
                name: str = a.ele("x:/b").text
                price: str = a.ele("x:/span[1]").text
                numbers: str = a.ele("x:/span[2]").text
                print("name:{},price:{},numbers:{}".format(name, price, numbers))


class ItemType:  # 物品类-物资的种类
    def __init__(self, name: str, num: float, price: float, id: str = "000") -> None:
        self.name: str = name  # 名称
        self.numbers: float = num  # 数量
        self.price: float = price  # 价格
        self.id: str = id  # 物品ID号


class BaseMain:
    def __init__(self, url: str = "https://www.simcompanies.com/landscape/") -> None:
        self.base_url = url  # 主基地页面
        """主基地页面"""
        self.closed_stores: list[ChromiumElement] = []
        """空闲的店铺"""

    # @pysnooper.snoop("file.log")
    def retail(self) -> None:
        """零售商店开始卖货"""
        count1: int = 0  # 计数器
        while 1:
            page_start_time: float = time.time()
            count1 += 1
            print("第{}次扫描商店状态".format(count1))
            self.get_closed_stores()
            if len(self.closed_stores) > 0:
                print("点击序列0的商店开始")
                self.closed_stores[0].click()
                print("点击序列0的商店结束")
                web.wait.load_start()
                web.wait.load_complete()
                time.sleep(5)
                # 获取库存
                try:
                    text1: str = web.ele(
                        'x://h3[text()="Diesel"]/../span', timeout=60
                    ).text
                    nums: float = number_str_to_float(text1)  # 库存DIESEL数量
                except ElementNotFoundError as e:
                    print(e)
                    break

                if nums > 1100:  # 判断库存是否充足
                    # 输入1小时销量，并找到合理价格

                    a1: str = web.ele('x://h3[text()="Diesel"]/../div').text  # 平均价格
                    a2: str = number_str_to_float(a1)
                    num1: float = round(float(a2) * 0.9, 2)  # 起步价

                    num2: float = round(float(a2) * 1.1, 2)  # 终止价

                    list1: list[dict] = []
                    try:
                        while num1 <= num2:  # 在价格区间
                            num1 = round(num1, 2)
                            # 输入销售数量 1hr
                            web.ele(
                                'x://h3[text()="Diesel"]/../../../../descendant::input[@placeholder="Quantity"]'
                            ).input(vals="2hr")
                            time.sleep(0.3)
                            # 输入销售价格
                            web.ele(
                                'x://h3[text()="Diesel"]/../../../../descendant::input[@placeholder="Price"]'
                            ).input(num1)
                            time.sleep(0.3)

                            web.ele(
                                'x://h3[text()="Diesel"]/../div/*'
                            ).click()  # 点击问号显示利润计算页面
                            time.sleep(1)
                            _money = web.ele("x://table/tbody/tr[5]/td[3]").text
                            _money = number_str_to_float(_money)
                            web.ele(
                                'x://div[text()="Retailing breakdown"]/button'
                            ).click()  # 点击关闭利润计算页面
                            time.sleep(0.8)
                            dict2: dict = {"售价": num1, "利润总和": _money}
                            list1.append(dict2)
                            print("当前字典是", dict2)
                            num1 += 0.1
                    except ElementNotFoundError as e:
                        print(e)
                        break

                    if len(list1) > 0:
                        good_price: dict = max(list1, key=lambda x: x["利润总和"])
                        # if (
                        #     good_price["售价"] > 55
                        #     or good_price["利润总和"] > 55
                        #     or good_price["利润总和"] == None
                        #     or 0
                        # ):
                        #     break

                        print(good_price, "是最佳")
                        # 输入1小时的最佳销PRICE
                        web.ele(
                            'x://h3[text()="Diesel"]/../../../../descendant::input[@placeholder="Price"]'
                        ).input(good_price["售价"])
                        # 点击销售按钮
                        web.ele(
                            'x://h3[text()="Diesel"]/../../../../descendant::button[text()="Sell"]'
                        ).click()
                    else:
                        break

                else:
                    # TODO 库存不足时，先合同采购
                    if self.buying_incoming_contracts():
                        print("合同采购成功")

                    else:
                        print("合同采购失败，进入交易所采购")
                        # 库存不足,且没有合同时，交易所采购
                        self.purchase_at_market_price()

            else:
                time.sleep(10)  # 间隔几秒扫描一次商店零售状态
                page_end_time: float = time.time()
                time2 = page_end_time - page_start_time
                if time2 > 300:  # 当在页面停留时间超过N秒后刷新页面
                    web.refresh()
                    web.wait.load_complete()

    # @pysnooper.snoop("file.log")
    def buying_incoming_contracts(self) -> bool:
        """从合同采购"""
        web.get(
            "https://www.simcompanies.com/headquarters/warehouse/incoming-contracts/",
            timeout=60,
        )
        web.wait.load_complete()
        time.sleep(5)
        # 合同定位，eles
        # //div[text()="Incoming contracts"]/../div[2]/div
        contracts: list[ChromiumElement] = web.eles(
            'x://div[text()="Incoming contracts"]/../div[2]/div', timeout=60
        )
        # 如果有合同
        if len(contracts) > 0:
            # TODO 创建列表 保存字典，便利每个元素加入字典，加入列表，选择价格最低且现金足够支付的合同购买
            dicts: list[dict] = []  # 存放每个合同信息
            # 当前现金数量
            _money: str = web.ele("x://nav/div/div/div[2]/div[1]/a/div/div[2]").text[1:]
            _price: float = number_str_to_float(_money)
            # 统计所有合同信息
            for i in contracts:
                # 获取价格文本
                _pr = i.ele("x://b").text[1:]
                # 价格的数字
                _pr = number_str_to_float(_pr)
                # /div[3]//span
                # 一份合同的总价款
                sum_money: str = i.ele("x:/div[3]//span").text[1:]
                sum_money: float = number_str_to_float(sum_money)
                dict0 = {"ele": i, "price": _pr, "sum_money": sum_money}
                dicts.append(dict0)
            good_dict: dict = {"price": 789, "sum_money": 789789}
            # 判断当前最佳合同
            for d in dicts:
                # 当前现金足够支付的,价格最低的
                if d["price"] < good_dict["price"] and _price - d["sum_money"] > 0:
                    good_dict = d
            if good_dict["price"] != 789 and good_dict["price"] < 40:
                # 点击购买合同按钮
                ele2: ChromiumElement = good_dict["ele"]
                ele2.ele('x:/div[3]//a[@aria-label="Sign contract"]').click()
                print("点击购买{c1}".format(c1=good_dict))
                return True
            else:
                return False
        else:
            return False

    # @pysnooper.snoop("file.log")
    def purchase_at_market_price(self):
        """从交易所采购"""
        # i_want_buy:list[str] = ['DIESEL','汽油']  11是汽油，12是DIESEL
        web.get(
            "https://www.simcompanies.com/zh/market/resource/12/", timeout=60
        )  # 打开交易所-DIESEL
        # 输入当前金额可购买的数量
        _price: float = float(
            web.ele(
                # 商品最低价格
                "x://table/tbody/tr[1]/td[4]/div/span"
            ).text[1:]
        )
        # 如果市场价高于 40，不买，返回
        if _price >= 38:
            time.sleep(2)
            return
        _money: str = web.ele(
            # 现金数量
            "x://nav/div/div/div[2]/div[1]/a/div/div[2]"
        ).text[1:]
        _c: float = number_str_to_float(_money)
        _buy_nums: float = _c / _price
        if _buy_nums >= 1000:
            _buy_nums = 1000
        web.ele('x://button[text()="Buy"]/../../descendant::input').input(
            vals=int(_buy_nums)
        )
        time.sleep(1)
        web.ele('x://button[text()="Buy"]').click()

    # @pysnooper.snoop("file.log")
    def get_closed_stores(self):
        """获取基地内所有空闲商店"""
        if "landscape" not in web.url:
            web.get(self.base_url, timeout=60)  # 打开主页面
        # 找到所有加油站
        petrol_stations: list[ChromiumElement] = web.eles(
            'x://span[text()="Gas station"]/../..', timeout=2
        )
        # 重置空闲加油站为0个
        self.closed_stores = []
        for i in petrol_stations:
            _a: list = i.eles('x:descendant::span[text()="Selling"]', timeout=0.2)
            _b: list = i.eles(
                'x://span[text()="Gas station"]/../..//b[text()="Rush for "]',
                timeout=0.2,
            )
            # //span[text()="Gas station"]/../..//b[text()="Rush for "]  升级状态
            if not (len(_a) > 0 or len(_b) > 0):  # 如果没有'正在零售Selling'字样就加list
                self.closed_stores.append(i)
        if len(self.closed_stores) > 0:
            today = datetime.now().strftime(r"%m-%d %H : %M : %S")
            print("空闲的商店有{}个，请注意,{}".format(len(self.closed_stores), today))


def main() -> None:
    """主函数"""
    base1 = BaseMain()
    count0 = 0
    while count0 < 1000:
        count0 += 1
        print("第{}次运行base1.retail()".format(count0))
        base1.retail()


if __name__ == "__main__":
    main()
